/*sm4加密
 */  


#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <stdint.h>  
#include "gmssl/sm4.h"
#include "gmssl/rand.h"
//生成密钥

#include "gmssl/rand.h"

// 定义明文最小长度  
#define PLAINTEXT_MIN_SIZE 130  
void duqu(char *filename, uint8_t **in, size_t *len) {

	FILE *file = fopen(filename, "rb");
	if (!file) {
		perror("Failed to open file");
		return;
	}

	fseek(file, 0, SEEK_END);
	*len = ftell(file);
	fseek(file, 0, SEEK_SET);

	*in = (uint8_t *)calloc(*len, 1);

	if (!*in) {
		perror("Failed to allocate memory");
		fclose(file);
		return;
	}

	fread(*in, 1, *len, file);
	fclose(file);
}
void duqu2(char *filename, char *in, int len) {

	FILE *file = fopen(filename, "rb");
	if (!file) {
		perror("Failed to open file");
		return;
	}

	fseek(file, 0, SEEK_END);
	len = ftell(file);
	fseek(file, 0, SEEK_SET);

	fread(in, 1, len, file);
	fclose(file);
}

void xieru(char *filename, uint8_t *out, size_t *len) {

	FILE *file = fopen(filename, "wb");
	if (!file) {
		perror("Failed to open file");
		return;
	}

	fwrite(out, sizeof(uint8_t), *len, file);
	fclose(file);
}



int main(int argc, char *argv[]){
	if(argc<4){
	printf("no enough filename\n");
	return 0;
	}  
    // 生成随机密钥  
    uint8_t key[SM4_KEY_SIZE];  
     

    // 生成随机IV  
    uint8_t iv[SM4_BLOCK_SIZE];  
    
	duqu2(argv[1], key, SM4_KEY_SIZE);
    
    duqu2(argv[2], iv, SM4_BLOCK_SIZE);  

     

    // 定义明文（不少于130字节）  
    uint8_t *plaintext;  
    size_t plaintext_len;
    
      
    duqu(argv[3], &plaintext, &plaintext_len);
    
    
    
    // 初始化 SM4 密钥结构  
    SM4_KEY enc_key, dec_key;  
    sm4_set_encrypt_key(&enc_key, key);  
    sm4_set_decrypt_key(&dec_key, key);  

    // 计算加密后可能的最大长度（明文长度 + 一个块的填充）    
    size_t max_ciphertext_len = plaintext_len + SM4_BLOCK_SIZE;  
    uint8_t *ciphertext = malloc(max_ciphertext_len);  
    if (ciphertext == NULL) {  
        fprintf(stderr, "内存分配失败。\n");  
        return EXIT_FAILURE;  
    }  

    // 由于加密和解密后的明文长度可能不同，预留足够的空间  
    uint8_t *decryptedtext = malloc(max_ciphertext_len + 1); // +1用于终止符  
    if (decryptedtext == NULL) {  
        fprintf(stderr, "内存分配失败。\n");  
        free(ciphertext);  
        return EXIT_FAILURE;  
    }  

    size_t outlen;  
    int ret;  

    // 加密带填充的明文  
    ret = sm4_cbc_padding_encrypt(&enc_key, iv, plaintext, plaintext_len, ciphertext, &outlen);  
    if (ret != 1) {  
        fprintf(stderr, "加密失败。\n");  
        free(ciphertext);  
        free(decryptedtext);  
        return EXIT_FAILURE;  
    }  

    // 输出密文（十六进制格式）  
     duqu(argv[3], &plaintext, &plaintext_len);
	 xieru(argv[4], ciphertext, &outlen);
    

    // 释放分配的内存  
    free(ciphertext);  
    free(decryptedtext);  

    return EXIT_SUCCESS;  
}
